<template>
  <div class="wraper" ref="wraper">
    <div class="canvas-wraper"><canvas id="canvas" ref="canvas"></canvas></div>
    <div class="contrlo-pencil">
      <div class="pencil-top">
        <template v-for="(item, idx) in toolsArr" >
          <el-popover v-model="isShowSizeBox" v-if="item.name == 'text'" :key="'top_'+idx" title="字体设置" placement="top" width="200" trigger="click">
            <div class="size-operation">
              <el-slider  :min="16" :max="88" v-model="sizeVal"></el-slider>
              <div class="size-btn" @click="isShowSizeBox=false;drawText()">确定</div>
            </div>
            <div slot="reference" class="pencil-top-item"
              @click="handleTools(item, idx)" :class="[initIdx == idx ? 'active' : '']">
              <img :src="'../../static/img/pencil/pencil' + (idx + 1) + '.png'" v-if="initIdx != idx" />
              <img :src="'../../static/img/pencil/pencil' + (idx + 1) + '-active.png'" v-else />
              <!-- <div class="size-operation" v-if="item.name">
             <el-slider v-model="sizeVal"></el-slider>
          </div> -->
            </div>
          </el-popover>
          <div v-else :key="'top_'+idx" class="pencil-top-item" @click="handleTools(item, idx)" :class="[initIdx == idx ? 'active' : '']">
              <img :src="'../../static/img/pencil/pencil' + (idx + 1) + '.png'" v-if="initIdx != idx" />
              <img :src="'../../static/img/pencil/pencil' + (idx + 1) + '-active.png'" v-else />
              <!-- <div class="size-operation" v-if="item.name">
             <el-slider v-model="sizeVal"></el-slider>
          </div> -->
            </div>
        </template>
        <div class="pencil-top-item" @click="$emit('noShowPencil')"><img
            :src="'../../static/img/pencil/pencil10.png'" /></div>
      </div>
      <div class="pencil-bottom">
        <div class="pencil-bottom-left">
          <div class="pencil-bl-item" v-for="(item, idx) in widthArray" :key="'bl_'+idx" @click="changeWidth(item,idx)"
            :class="[initWidthIdx == idx ? 'active' : '']"><span
              :style="'width:' + item.value + 'px;height:'+item.value+'px'"></span></div>
        </div>
        <div class="pencil-bottom-right">
          <div class="now-color">
            <span :style="'background-color:' + drawColor + ' ;'"></span>
          </div>
          <div class="right-color">
            <div class="rc-item" v-for="(item, idx) in colorArray" :key="'rc_'+idx" @click="changeColor(item,idx)"
              :class="[initColorIdx == idx ? 'active' : '']"><span
                :style="'background-color:' + item.value + ' ;'"></span></div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  import {
    fabric
  } from 'fabric';
  export default {
    data() {
      return {
        sizeVal: 36,
        isShowSizeBox:false,
        currentTool: '',
        done: false,
        fabricObj: null,
        initIdx: 0,
        initColorIdx: 0,
        initWidthIdx: 1,
        toolsArr: [{
            name: 'pencil',
            icon: ' icon-pencil'
          },
          {
            name: 'rectangle',
            icon: ' icon-juxing'
          },
          {
            name: 'circle',
            icon: ' icon-yuanxing'
          },
          {
            name: 'line',
            icon: ' icon-line'
          },
          {
            name: 'text',
            icon: ' icon-ziti'
          },
          {
            name: 'arrow',
            icon: ' icon-arrow'
          },
          {
            name: 'equilateral', //TODO白板
            icon: ' icon-sanjiaoxing'
          },
          {
            name: 'undo',
            icon: ' icon-huitui'
          },
          {
            name: 'reset',
            icon: ' icon-reset'
          }
        ],
        mouseFrom: {},
        mouseTo: {},
        moveCount: 1,
        doDrawing: false,
        fabricHistoryJson: [],
        mods: 0,
        drawingObject: null, //绘制对象
        drawColor: '#000000',
        drawWidth: 4,
        imageBase64: '',
        zoom: window.zoom ? window.zoom : 1,
        colorArray: [{
            value: '#000000'
          },
          {
            value: '#AAAAAA'
          },
          {
            value: '#A70404'
          },
          {
            value: '#FD8634'
          },
          {
            value: '#01A22C'
          },
          {
            value: '#195AEA'
          },
          {
            value: '#A109E5'
          },
          {
            value: '#18A6C7'
          },
          {
            value: '#FFFFFF'
          },
          {
            value: '#777777'
          },
          {
            value: '#FF0000'
          },
          {
            value: '#F0DF16'
          },
          {
            value: '#99E82E'
          },
          {
            value: '#44A8FD'
          },
          {
            value: '#F130F8'
          },
          {
            value: '#4AF0F0'
          }
        ],
        widthArray: [{
            value: 1
          },
          {
            value: 4
          },
          {
            value: 12
          },
        ]
      };
    },
    mounted() {
      //初始化canvas
      this.initCanvas();
    },
    computed: {
      canvasWidth() {
        return window.innerWidth;
      },
      canvasHeight() {
        return window.innerHeight;
      }
    },
    methods: {
      initCanvas() {
        this.fabricObj = new fabric.Canvas('canvas', {
          isDrawingMode: true,
          selectable: false,
          selection: false,
          devicePixelRatio: true //Retina 高清屏 屏幕支持
        });
        this.fabricObj.freeDrawingBrush.color = this.drawColor;
        this.fabricObj.freeDrawingBrush.width = this.drawWidth;
        this.fabricObj.setWidth(this.canvasWidth);
        this.fabricObj.setHeight(this.canvasHeight);
        //绑定画板事件
        this.fabricObjAddEvent();
      },
      changeColor(item, idx) {
        this.initColorIdx = idx;
        this.drawColor = item.value;
        this.fabricObj.freeDrawingBrush.color = item.value;
      },
      changeWidth(item, idx) {
        this.initWidthIdx = idx;
        this.drawWidth = item.value;
        this.fabricObj.freeDrawingBrush.width = item.value;
      },
      //时间监听
      fabricObjAddEvent() {
        this.fabricObj.on({
          'mouse:down': o => {
            this.mouseFrom.x = o.pointer.x;
            this.mouseFrom.y = o.pointer.y;
            this.doDrawing = true;
            if (this.currentTool == 'text') {
              this.drawText();
            }
          },
          'mouse:up': o => {
            this.mouseTo.x = o.pointer.x;
            this.mouseTo.y = o.pointer.y;
            this.drawingObject = null;
            this.moveCount = 1;
            this.doDrawing = false;
            this.updateModifications(true);
          },
          'mouse:move': o => {
            if (this.moveCount % 2 && !this.doDrawing) {
              //减少绘制频率
              return;
            }
            this.moveCount++;
            this.mouseTo.x = o.pointer.x;
            this.mouseTo.y = o.pointer.y;
            this.drawing();
          },
          //对象移动时间
          'object:moving': e => {
            e.target.opacity = 0.5;
          },
          //增加对象
          'object:added': () => {
            // debugger
          },
          'object:modified': e => {
            e.target.opacity = 1;
            // let object = e.target;
            this.updateModifications(true);
          },
          'selection:created': e => {
            if (e.target._objects) {
              //多选删除
              var etCount = e.target._objects.length;
              for (var etindex = 0; etindex < etCount; etindex++) {
                this.fabricObj.remove(e.target._objects[etindex]);
              }
            } else {
              //单选删除
              this.fabricObj.remove(e.target);
            }
            this.fabricObj.discardActiveObject(); //清楚选中框
            this.updateModifications(true);
          }
        });
      },
      //储存历史记录
      updateModifications(savehistory) {
        if (savehistory == true) {
          this.fabricHistoryJson.push(JSON.stringify(this.fabricObj));
        }
      },
      //canvas 历史后退
      undo() {
        let state = this.fabricHistoryJson;
        if (this.mods < state.length) {
          this.fabricObj.clear().renderAll();
          this.fabricObj.loadFromJSON(state[state.length - 1 - this.mods - 1]);
          this.fabricObj.renderAll();
          this.mods += 1;
        }
      },
      //前进
      redo() {
        let state = this.fabricHistoryJson;
        if (this.mods > 0) {
          this.fabricObj.clear().renderAll();
          this.fabricObj.loadFromJSON(state[state.length - 1 - this.mods + 1]);
          this.fabricObj.renderAll();
          this.mods -= 1;
        }
      },
      transformMouse(mouseX, mouseY) {
        return {
          x: mouseX / this.zoom,
          y: mouseY / this.zoom
        };
      },
      resetObj() {
        this.fabricObj.selectable = false;
        this.fabricObj.selection = false;
        this.fabricObj.skipTargetFind = true;
        //清除文字对象
        if (this.textboxObj) {
          this.textboxObj.exitEditing();
          this.textboxObj = null;
        }
      },
      handleTools(tools, idx) {
        this.initIdx = idx;
        this.currentTool = tools.name;
        this.fabricObj.isDrawingMode = false;
        this.resetObj();
        switch (tools.name) {
          case 'pencil':
            this.fabricObj.isDrawingMode = true;
            break;
          case 'remove':
            this.fabricObj.selection = true;
            this.fabricObj.skipTargetFind = false;
            this.fabricObj.selectable = true;
            break;
          case 'reset':
            this.fabricObj.clear();
            break;
          case 'redo':
            this.redo();
            break;
          case 'undo':
            this.undo();
            break;
          default:
            break;
        }
      },
      //绘制文字对象
      drawText() {
        this.textboxObj = new fabric.Textbox(' ', {
          left: this.mouseFrom.x,
          top: this.mouseFrom.y,
          width: 220,
          fontSize: this.sizeVal,
          fill: this.drawColor,
          hasControls: true
        });
        this.fabricObj.add(this.textboxObj);
        this.textboxObj.enterEditing();
        this.textboxObj.hiddenTextarea.focus();
        this.updateModifications(true);
      },
      drawing() {
        if (this.drawingObject) {
          this.fabricObj.remove(this.drawingObject);
        }
        let fabricObject = null;
        switch (this.currentTool) {
          case 'pencil':
            this.fabricObj.isDrawingMode = true;
            break;
          case 'line':
            fabricObject = new fabric.Line([this.mouseFrom.x, this.mouseFrom.y, this.mouseTo.x, this.mouseTo.y], {
              stroke: this.drawColor,
              strokeWidth: this.drawWidth
            });
            break;
          case 'arrow':
            fabricObject = new fabric.Path(this.drawArrow(this.mouseFrom.x, this.mouseFrom.y, this.mouseTo.x, this
              .mouseTo.y, 15.5, 15.5), {
              stroke: this.drawColor,
              fill: 'rgba(255,255,255,0)',
              strokeWidth: this.drawWidth
            });
            break;
          case 'dashedline':
            // doshed line
            fabricObject = this.drawDoshedLine();
            break;
          case 'rectangle':
            // 矩形
            fabricObject = this.drawRectangle();
            break;
          case 'circle': //正圆
            fabricObject = this.drawCircle();
            break;
          case 'ellipse':
            // 椭圆
            fabricObject = this.drawEllipse();
            break;
          case 'equilateral': //等边三角形
            fabricObject = this.drawTriangle();
            break;
          case 'remove':
            break;
          default:
            // statements_def'
            break;
        }
        if (fabricObject) {
          this.$nextTick(() => {
            this.fabricObj.add(fabricObject);
            this.drawingObject = fabricObject;
          });
        }
      },
      // dashed line
      drawDoshedLine() {
        return new fabric.Line([this.mouseFrom.x, this.mouseFrom.y, this.mouseTo.x, this.mouseTo.y], {
          strokeDashArray: [10, 3],
          stroke: this.drawColor,
          strokeWidth: this.drawWidth
        });
      },
      // circle
      drawCircle() {
        let radius =
          Math.sqrt((this.mouseTo.x - this.mouseFrom.x) * (this.mouseTo.x - this.mouseFrom.x) + (this.mouseTo.y - this
            .mouseFrom.y) * (this.mouseTo.y - this.mouseFrom.y)) / 2;
        return new fabric.Circle({
          left: this.mouseFrom.x,
          top: this.mouseFrom.y,
          stroke: this.drawColor,
          fill: 'rgba(255, 255, 255, 0)',
          radius: radius,
          strokeWidth: this.drawWidth
        });
      },
      // triangle
      drawTriangle() {
        let height = this.mouseTo.y - this.mouseFrom.y;
        return new fabric.Triangle({
          top: this.mouseFrom.y,
          left: this.mouseFrom.x,
          width: Math.sqrt(Math.pow(height, 2) + Math.pow(height / 2.0, 2)),
          height: height,
          stroke: this.drawColor,
          strokeWidth: this.drawWidth,
          fill: 'rgba(255,255,255,0)'
        });
      },
      // ellipse
      drawEllipse() {
        let left = this.mouseFrom.x;
        let top = this.mouseFrom.y;
        // let ellipse = Math.sqrt((this.mouseTo.x - left) * (this.mouseTo.x - left) + (this.mouseTo.y - top) * (this.mouseTo.y - top)) / 2;
        return new fabric.Ellipse({
          left: left,
          top: top,
          stroke: this.drawColor,
          fill: 'rgba(255, 255, 255, 0)',
          originX: 'center',
          originY: 'center',
          rx: Math.abs(left - this.mouseTo.x),
          ry: Math.abs(top - this.mouseTo.y),
          strokeWidth: this.drawWidth
        });
      },
      // rectangle
      drawRectangle() {
        return new fabric.Rect({
          left: this.mouseFrom.x,
          top: this.mouseFrom.y,
          width: this.mouseTo.x - this.mouseFrom.x,
          height: this.mouseTo.y - this.mouseFrom.y,
          fill: 'rgba(255, 255, 255, 0)',
          stroke: this.drawColor,
          strokeWidth: this.drawWidth
        });
      },
      //书写箭头的方法
      drawArrow(fromX, fromY, toX, toY, theta, headlen) {
        theta = typeof theta != 'undefined' ? theta : 30;
        headlen = typeof theta != 'undefined' ? headlen : 10;
        // 计算各角度和对应的P2,P3坐标
        let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI,
          angle1 = ((angle + theta) * Math.PI) / 180,
          angle2 = ((angle - theta) * Math.PI) / 180,
          topX = headlen * Math.cos(angle1),
          topY = headlen * Math.sin(angle1),
          botX = headlen * Math.cos(angle2),
          botY = headlen * Math.sin(angle2);
        let arrowX = fromX - topX,
          arrowY = fromY - topY;
        let path = ' M ' + fromX + ' ' + fromY;
        path += ' L ' + toX + ' ' + toY;
        arrowX = toX + topX;
        arrowY = toY + topY;
        path += ' M ' + arrowX + ' ' + arrowY;
        path += ' L ' + toX + ' ' + toY;
        arrowX = toX + botX;
        arrowY = toY + botY;
        path += ' L ' + arrowX + ' ' + arrowY;
        return path;
      },
      downLoadImage() {
        this.done = true;
        //生成双倍像素比的图片
        let base64URl = this.fabricObj.toDataURL({
          formart: 'png',
          multiplier: 2
        });
        this.imageBase64 = base64URl;
        this.done = false;
      }
    }
  };

</script>

<style lang="scss" scoped>
  .wraper {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 9;
    width: 100%;
    height: 100vh;

    .canvas-wraper {
      height: 100%;
      width: 100%;
      margin-bottom: 10px;
      overflow: hidden;
    }

    .contrlo-pencil {
      position: absolute;
      bottom: 50px;
      left: 50%;
      transform: translate(-50%, 0);
      width: 380px;
      background: rgba(0, 0, 0, 0.6);
      border-radius: 20px;

      .pencil-top {
        display: flex;
        border-bottom: 2px solid #777777;

        .pencil-top-item {
          flex: 1;
          text-align: center;
          padding-top: 4px;
          padding-bottom: 4px;

          &.acitve {}

          img {
            width: 34px;
          }
        }
      }

      .pencil-bottom {
        display: flex;

        .pencil-bottom-left {
          display: flex;
          align-items: center;
          border-right: 2px solid #777777;
          padding: 0 10px;

          .pencil-bl-item {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 30px;
            height: 30px;

            &.active {
              background-color: #666666;
            }

            span {
              display: block;
              width: 10px;
              height: 10px;
              border-radius: 50%;
              background-color: #ffffff;
            }

          }
        }

        .pencil-bottom-right {
          flex: 1;
          display: flex;

          .now-color {
            padding: 10px;

            span {
              width: 40px;
              height: 40px;
              display: block;
            }
          }

          .right-color {
            flex: 1;
            display: flex;
            flex-wrap: wrap;
            padding: 6px 20px 6px 0;

            .rc-item {
              cursor: pointer;
              width: 12.5%;
              padding: 2px 0;

              &.active {
                span {
                  border: 1px solid #54E3C1;
                }
              }

              span {
                border: 1px solid #707070;
                display: block;
                margin: auto;
                width: 20px;
                height: 20px;
                background-color: #ffffff;
              }
            }
          }
        }
      }
    }

    .controlPanel {
      position: absolute;
      bottom: 50px;
      left: 50%;
      transform: translate(-50%, 0);
      width: 100%;
      height: 62px;
      background: #ddd;
      display: flex;
      justify-content: center;
      align-items: center;

      .contro-item {
        flex-basis: 100px;
        border-right: 1px solid #dad7d9;
        text-align: center;
        cursor: pointer;
        background: #fefefe;

        i {
          font-size: 38px;
          line-height: 62px;
        }

        &.active {
          background: #e34f51;
          color: #fff;
          border-radius: 3px;

          i {
            font-size: 42px;
          }
        }
      }
    }

    .download {
      img {
        width: 100%;
      }
    }
  }
  .size-btn{
    width: 60px;
    color: #333;
    font-size: 14px;
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 4px 0px;
    margin-left: auto;
    text-align: center;
    cursor: pointer;
  }

</style>
